home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue54 / Persist / tiPtnVisitor.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2000-01-23  |  9.2 KB  |  317 lines

  1. {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2.   (c) TechInsite Pty. Ltd.
  3.   PO Box 429, Abbotsford, Melbourne. 3067 Australia
  4.   Phone: +61 3 9419 6456
  5.   Fax:   +61 3 9419 1682
  6.   Web:   www.techinsite.com.au
  7.   EMail: peter_hinrichsen@techinsite.com.au
  8.  
  9.   Created: Jan 2000
  10.  
  11.   Notes: Family of abstract classes to provide functionality of the
  12.          Vistior Pattern
  13.  
  14. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
  15. unit tiPtnVisitor;
  16.  
  17. interface
  18. uses
  19.   Classes
  20.   ;
  21.  
  22. type
  23.  
  24.   // TVisitedAbs forward declaration
  25.   TVisitedAbs = class ;
  26.  
  27.   // TVisitorAbs: The class that does the visiting
  28.   //----------------------------------------------------------------------------
  29.   TVisitorAbs = class( TObject )
  30.   private
  31.     FVisited   : TVisitedAbs ;
  32.   protected
  33.     function    AcceptVisitor : boolean ; virtual ;
  34.   public
  35.     constructor create ; virtual ;
  36.     procedure   execute( pVisited : TVisitedAbs ) ; virtual ;
  37.  
  38.     property    Visited   : TVisitedAbs read FVisited write FVisited ;
  39.  
  40.   end ;
  41.  
  42.   // TVisitorClass reference
  43.   //----------------------------------------------------------------------------
  44.   TVisitorClass = class of TVisitorAbs ;
  45.  
  46.   // TVisitedAbs
  47.   // Descends from TTransportAbstract, for streaming...
  48.   // The class that gets visited.
  49.   //----------------------------------------------------------------------------
  50.   TVisitedAbs = class( TPersistent )
  51.   private
  52.     FbSelfIterate: boolean;
  53.   protected
  54.     function    GetCaption : string ; virtual ;
  55.   published
  56.   public
  57.     constructor create ; virtual ;
  58.     procedure   Iterate( pVisitor : TVisitorAbs ) ; virtual ;
  59.     property    SelfIterate : boolean read FbSelfIterate write FbSelfIterate ;
  60.     property    Caption     : string  read GetCaption ;
  61.   end ;
  62.  
  63.   // A wrapper for the TList which allows its elements to be visited
  64.   //----------------------------------------------------------------------------
  65.   TVisList = class( TVisitedAbs )
  66.   private
  67.     FList   : TList ;
  68.     FsName: string;
  69.  
  70.     function    GetCount: integer;
  71.     function    GetItems(i:integer): TObject;
  72.     procedure   SetItems(i: integer; const Value: TObject);
  73.  
  74.   protected
  75.     function    GetCaption : string ; override ;
  76.   public
  77.     constructor create ; override;
  78.     constructor CreateExt( const psName : string ) ;
  79.     destructor  destroy ; override ;
  80.  
  81.     procedure   Iterate( pVisitor : TVisitorAbs ) ; override ;
  82.     property    Count : integer read GetCount ;
  83.     property    Items[i:integer] : TObject read GetItems write SetItems ;
  84.     procedure   Delete( i : integer ) ;
  85.     procedure   Add( pObject : TObject ) ;
  86.     procedure   Clear ;
  87.     property    List : TList read FList ;
  88.     property    Name : string read FsName write FsName ;
  89.     function    IndexOf( pData : TObject ) : integer ;
  90.     function    LastItem : TObject ; virtual ;
  91.   end ;
  92.  
  93.   // A wrapper for the TStream which allows text to be written to the stream
  94.   // with each visit.
  95.   //----------------------------------------------------------------------------
  96.   TVisStream = class( TVisitorAbs )
  97.   private
  98.     FStream : TStream ;
  99.   protected
  100.     procedure Write( const psValue : string ) ;
  101.     procedure WriteLn( const psValue : string ) ;
  102.   public
  103.     property  Stream : TStream read FStream write FStream ;
  104.   end ;
  105.  
  106.   TVisStreamClass = class of TVisStream ;
  107.  
  108. implementation
  109. uses
  110.    SysUtils  // Exception
  111.   ,tiUtils   // GetPropNames
  112.   ,TypInfo   // GetObjectProp
  113.   ;
  114.  
  115. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  116. // *
  117. // * TVisitedAbs
  118. // *
  119. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  120. constructor TVisitedAbs.create;
  121. begin
  122.   inherited create ;
  123. end;
  124.  
  125. //------------------------------------------------------------------------------
  126. function TVisitedAbs.GetCaption: string;
  127. begin
  128.   result := className ;
  129. end;
  130.  
  131. //------------------------------------------------------------------------------
  132. procedure TVisitedAbs.Iterate(pVisitor: TVisitorAbs) ;
  133. var
  134.   lsl      : TStringList ;
  135.   i        : integer ;
  136.   j        : integer ;
  137.   lVisited : TObject ;
  138. begin
  139.   Assert( pVisitor <> nil, 'Visitor unassigned' ) ;
  140.   try
  141.     pVisitor.Execute( self ) ;
  142.  
  143.     // If SelfIterate is true, then use RTTI to scan through all the
  144.     // properties of type TVisitedAbs
  145.       // Create a string list to hold the property names
  146.       lsl := TStringList.Create ;
  147.       try
  148.         // Get all property names of type tkClass
  149.         tiGetPropertyNames( self, lsl, [tkClass] ) ;
  150.         // Scan through these properties
  151.         for i := 0 to lsl.Count - 1 do begin
  152.           // Get a pointer to the property
  153.  
  154.           lVisited := GetObjectProp( self, lsl.Strings[i] ) ;
  155.  
  156.           // If the property is a TVisitedAbs, then visit it.
  157.           if ( lVisited is TVisitedAbs ) then
  158.             TVisitedAbs( lVisited ).Iterate( pVisitor ) ;
  159.  
  160.           // If the property is a TList, then visit it's items
  161.           if (lVisited is TList ) then
  162.             for j := 0 to TList( lVisited ).Count - 1 do
  163.               if ( TObject( TList( lVisited ).Items[j] ) is TVisitedAbs ) then
  164.                 TVisitedAbs( TList( lVisited ).Items[j] ).Iterate( pVisitor ) ;
  165.  
  166.         end ;
  167.       finally
  168.         lsl.Free ;
  169.       end ;
  170.  
  171.   except
  172.     on e:exception do
  173.       raise exception.Create( 'Error processing visitor: ' + pVisitor.ClassName + #13 +
  174.                               'Called in ' + ClassName + '.Iterate.' + #13 +
  175.                               'Message: ' + e.message ) ;
  176.   end ;
  177.  
  178. end ;
  179.  
  180. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  181. // *
  182. // * TVisitorAbs
  183. // *
  184. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  185. function TVisitorAbs.AcceptVisitor : boolean;
  186. begin
  187.   result := true ;
  188. end;
  189.  
  190. //------------------------------------------------------------------------------
  191. constructor TVisitorAbs.create;
  192. begin
  193.   inherited create ;
  194. end;
  195.  
  196. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  197. // *
  198. // * TVisList
  199. // *
  200. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  201. procedure TVisList.Add(pObject: TObject);
  202. begin
  203.   FList.Add( pObject ) ;
  204. end;
  205.  
  206. //------------------------------------------------------------------------------
  207. procedure TVisList.Clear;
  208. var
  209.   i : integer ;
  210. begin
  211.   for i := FList.Count - 1 downto 0 do
  212.     if Assigned( FList.Items[ i ] ) then
  213.       TObject( FList.Items[ i ] ).Free ;
  214.   FList.Clear ;
  215. end;
  216.  
  217. //------------------------------------------------------------------------------
  218. constructor TVisList.create;
  219. begin
  220.   inherited create ;
  221.   FList := TList.Create ;
  222. end;
  223.  
  224. //------------------------------------------------------------------------------
  225. constructor TVisList.CreateExt(const psName: string);
  226. begin
  227.   Create ;
  228.   Name := psName ;
  229. end;
  230.  
  231. //------------------------------------------------------------------------------
  232. procedure TVisList.Delete(i: integer);
  233. begin
  234.   FList.Delete( i ) ;
  235. end;
  236.  
  237. //------------------------------------------------------------------------------
  238. destructor TVisList.destroy;
  239. begin
  240.   clear ;
  241.   FList.Free ;
  242.   inherited ;
  243. end;
  244.  
  245. //------------------------------------------------------------------------------
  246. function TVisList.GetCaption: string;
  247. begin
  248.   result := Name ;
  249. end;
  250.  
  251. //------------------------------------------------------------------------------
  252. function TVisList.GetCount: integer;
  253. begin
  254.   result := FList.Count ;
  255. end;
  256.  
  257. //------------------------------------------------------------------------------
  258. function TVisList.GetItems(i:integer): TObject;
  259. begin
  260.   result := FList.Items[i] ;
  261. end;
  262.  
  263. //------------------------------------------------------------------------------
  264. function TVisList.IndexOf(pData : TObject ) : integer ;
  265. begin
  266.   result := FList.IndexOf( pData ) ;
  267. end;
  268.  
  269. //------------------------------------------------------------------------------
  270. procedure TVisList.Iterate(pVisitor: TVisitorAbs);
  271. var
  272.   i : integer ;
  273. begin
  274.   inherited iterate( pVisitor ) ;
  275.   for i := 0 to Count - 1 do
  276.     ( TObject( Items[i] ) as TVisitedAbs ).Iterate( pVisitor ) ;
  277. end;
  278.  
  279. //------------------------------------------------------------------------------
  280. function TVisList.LastItem: TObject;
  281. begin
  282.   result := Items[Count-1] ;
  283. end;
  284.  
  285. //------------------------------------------------------------------------------
  286. procedure TVisList.SetItems(i: integer; const Value: TObject);
  287. begin
  288.   FList.Items[i] := Value ;
  289. end;
  290.  
  291. //------------------------------------------------------------------------------
  292. procedure TVisStream.Write(const psValue: string);
  293. var
  294.   lpcValue : PChar ;
  295. begin
  296.   lpcValue := PChar( psValue ) ;
  297.   FStream.WriteBuffer( lpcValue^, length( lpcValue )) ;
  298. end;
  299.  
  300. //------------------------------------------------------------------------------
  301. procedure TVisStream.WriteLn(const psValue: string);
  302. begin
  303.   Write( psValue + #13 + #10 ) ;
  304. end ;
  305.  
  306. //------------------------------------------------------------------------------
  307. procedure TVisitorAbs.execute(pVisited: TVisitedAbs);
  308. begin
  309.   Visited := pVisited ;
  310. end;
  311.  
  312. end.
  313.  
  314.  
  315.  
  316.  
  317.